<!--
 * @Description: Stay hungry，Stay foolish
 * @Author: ''
 * @Date: 2023-09-19 14:05:30
 * @LastEditTime: 2023-09-19 15:21:33
 * @LastEditors: ''
-->
<template>
  <div :class="prefixCls" ref="root">
    <slot name="prefix" :class="prefixCls+'prefix'"></slot>
    <template v-if="computedReady">
      <Tooltip v-if="tooltip" :content="text" :theme="theme" :max-width="maxWidth" :placement="placement" :transfer="transfer">
        <span :class="prefixCls+'text'" ref="textRef">{{text}}</span>
        <span :class="prefixCls+'more'" ref="moreRef" v-show="oversize"><slot name="more">...</slot></span>
        <slot name="suffix" :class="prefixCls+'suffix'"></slot>
      </Tooltip>
      <template v-else>
        <span :class="prefixCls+'text'" ref="textRef">{{text}}</span>
        <span :class="prefixCls+'more'" ref="moreRef" v-show="oversize"><slot name="more">...</slot></span>
        <slot name="suffix" :class="prefixCls+'suffix'"></slot>
      </template>
    </template>
    <div :class="prefixCls+'hidden'" v-else>
      <span :class="prefixCls+'text'" ref="textRef">{{text}}</span>
      <span :class="prefixCls+'more'" ref="moreRef" v-show="oversize"><slot name="more">...</slot></span>
      <slot name="suffix" :class="prefixCls+'suffix'"></slot>
    </div>
  </div>
</template>


<script setup>
defineOptions({
  name: 'Ellipsis'
})

import {ref, getCurrentInstance, watch,onMounted,nextTick} from "vue"

const prefixCls=ref('haloe-ellipsis')
import Tooltip from "../tooltip/tooltip-v2.vue"
import {oneOf,getStyle} from "../../utils/assist"

const props=defineProps({
  text: {
    type: String
  },
  // 限制高度
  height: {
    type: Number
  },
  // 限制行数，将换算为 height。如果设置了 height，则直接使用 height 计算
  lines: {
    type: Number
  },
  // 按照指定长度截取
  length: {
    type: Number
  },
  // 是否将全角字符的长度视为2来计算字符串长度，适用于 length
  fullWidthRecognition: {
    type: Boolean,
    default: false
  },
  // todo 是否自动根据外层宽度动态改变
  autoResize: {
    type: Boolean,
    default: false
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  },
  // 是否开启 tooltip
  tooltip: {
    type: Boolean,
    default: false
  },
  // 以下是 tooltip 部分选项
  transfer: {
    type: Boolean,
    default () {
      const global = getCurrentInstance().appContext.config.globalProperties;
      return !global.$HALOE || global.$HALOE.transfer === '' ? false : global.$HALOE.transfer;
    }
  },
  theme: {
    validator (value) {
      return oneOf(value, ['dark', 'light']);
    },
    default: 'dark'
  },
  maxWidth: {
    type: [String, Number],
    default: 250
  },
  placement: {
    validator (value) {
      return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
    },
    default: 'bottom'
  },
})

const emits=defineEmits(['on-show', 'on-hide'])
const instance =getCurrentInstance()
let oversize=ref(false)
let computedReady=ref(false)  // 先隐形计算，计算好后，再根据配置显示
let computedText=ref('')  // 计算后的 text 内容
let root=ref();
let textRef=ref()
let moreRef=ref();

const getStrFullLength = (str = '') =>
  str.split('').reduce((pre, cur) => {
    const charCode = cur.charCodeAt(0);
    if (charCode >= 0 && charCode <= 128) {
      return pre + 1;
    }
    return pre + 2;
  }, 0);

const cutStrByFullLength = (str = '', maxLength) => {
  let showLength = 0;
  return str.split('').reduce((pre, cur) => {
    const charCode = cur.charCodeAt(0);
    if (charCode >= 0 && charCode <= 128) {
      showLength += 1;
    } else {
      showLength += 2;
    }
    if (showLength <= maxLength) {
      return pre + cur;
    }
    return pre;
  }, '');
};

const computeText= ()=> {
  oversize.value = false;
  computedReady.value = false;
  // const instance =getCurrentInstance()
  nextTick(() => {
    let $text = textRef.value;
    
    // console.log('instance',instance)
    let $el = root.value;

    let $more = moreRef.value;
    let n = 1000;
    let text = props.text;
    let height = props.height;
    // 当 height 未定义，且 lines 定义时，计算真实高度，否则使用 this.height
    if (!height && props.lines) {
      const lineHeight = parseInt(getStyle($el, 'lineHeight'), 10);
      height = lineHeight * props.lines;
    }

    if($text) {
      // 指定 length，则按具体字数剪裁
      if (props.length) {
        const textLength = props.fullWidthRecognition ? getStrFullLength(text) : text.length;
        if (textLength > props.length) {
          oversize.value = true;
          $more.style.display = 'inline-block';
          text = props.fullWidthRecognition ? cutStrByFullLength(text, props.length) : text.slice(0, props.length);
        }
      } else {
        if($el.offsetHeight > height) {
          oversize.value = true;
          $more.style.display = 'inline-block';

          while ($el.offsetHeight > height && n > 0) {
            if($el.offsetHeight > height * 3) {
              $text.innerText = text = text.substring(0, Math.floor(text.length / 2));
            } else {
              $text.innerText = text = text.substring(0, text.length - 1);
            }
            n--;
          }
        }
      }
    }
    // console.log('text',text)
    computedText.value = text;
  });
}

const limitShow =()=> {
  computedReady.value = true;
  // const instance =getCurrentInstance()
  nextTick(() => {
    let $text = textRef.value;
    // let $el = this.$el;
    // const instance =getCurrentInstance()
    let $el = root.value;
    // console.log('$el',$el)
    // console.log('textRef',textRef.value)
    if ($text) {
      $text.innerText = computedText.value;
      if ($el.offsetHeight > props.height) {
        emits('on-hide');
      } else {
        emits('on-show');
      }
    }
  });
}

const init=()=> {
  if (!props.disabled) {
    computeText();
    limitShow();
  }
}

onMounted(() => {
  init()
})

watch(()=>props.disabled,()=>{
  init()
})

watch(()=>props.text,()=>{
  init();
})

watch(()=>props.height,()=>{
  init()
})
</script>